package com.iplant.basic.controller.bpm;

import com.iplant.base.controller.BaseController;
import com.iplant.base.po.APIResult;
import com.iplant.base.po.Pagination;
import com.iplant.base.po.ServiceResult;
import com.iplant.base.utils.RetCode;
import com.iplant.base.utils.serializer.CloneTool;
import com.iplant.base.utils.general.StringUtils;
import com.iplant.basic.service.BPMService;
import com.iplant.basic.service.basicenum.bpm.BPMEventModule;
import com.iplant.basic.service.basicenum.bpm.BPMHistoryTaskStatus;
import com.iplant.basic.service.basicenum.bpm.BPMTaskStatus;
import com.iplant.basic.service.bpm.BPMTaskService;
import com.iplant.basic.service.po.bms.BMSEmployee;
import com.iplant.basic.service.po.bpm.BPMActivitiHisTask;
import com.iplant.basic.service.po.bpm.BPMActivitiProcessInstance;
import com.iplant.basic.service.po.bpm.BPMActivitiTask;
import com.iplant.basic.service.po.bpm.BPMTaskBase;
import com.iplant.basic.utils.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@RestController
@RequestMapping("/api/Runtime")
public class BPMRuntimeController extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(BPMRuntimeController.class);


    @Autowired
    public BPMService mBPMService;


    /**
     * 查询任务（网页版）
     */
    @GetMapping("/EmployeeAllWeb")
    public Object EmployeeAllWeb(HttpServletRequest request) {
        Object wResult = new Object();
        try {
            BMSEmployee wLoginUser = GetSession(request);

            Map<String, Object> wParams = GetParamsMap(request);

            if (!wParams.containsKey("Status")) {
                return GetResult(RetCode.SERVER_CODE_ERR, RetCode.SERVER_RST_ERROR_OUT);
            }

            int wModuleID = StringUtils.parseInt(request.getParameter("ModuleID"));
            BPMEventModule wEventID = BPMEventModule.getEnumType(wModuleID);

            if (!Constants.BPMServiceMap.containsKey(wEventID)) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, "该流程暂不支持");
                return wResult;
            }

            BPMTaskService wBPMTaskService = Constants.BPMServiceMap.get(wEventID);

            Pagination wPagination = GetPagination(request);

            ServiceResult<List<? extends BPMTaskBase>> wServiceResult =
                    wBPMTaskService.BPM_QueryEmployeeAllWeb(wLoginUser, wParams, wPagination);

            if (StringUtils.isEmpty(wServiceResult.FaultCode)) {
                wResult = GetResult(RetCode.SERVER_CODE_SUC, "", wServiceResult.Result, wPagination.getTotalPage());
            } else {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, wServiceResult.FaultCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
            wResult = GetResult(RetCode.SERVER_CODE_ERR, ex.toString());
        }
        return wResult;
    }


    /**
     * 创建流程任务
     */
    @PostMapping("/startProcessByProcessDefinitionKey")
    public Object startProcessByProcessDefinitionKey(HttpServletRequest request,
                                                     @RequestBody Map<String, Object> wParam) {
        Map<String, Object> wResult = new HashMap<>();
        try {
            BMSEmployee wLoginUser = GetSession(request);

            if (!wParam.containsKey("processDefinitionKey")) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, RetCode.SERVER_RST_ERROR_OUT);
                return wResult;
            }

            String wModuleIDString = StringUtils.parseString(wParam.get("processDefinitionKey"));
            if (wModuleIDString.startsWith("_")) {
                wModuleIDString = wModuleIDString.substring(1);
            }
            int wModuleID = StringUtils.parseInt(wModuleIDString);

            int wTaskID = StringUtils.parseInt(wParam.get("TaskID"));

            BPMEventModule wEventID = BPMEventModule.getEnumType(wModuleID);

            if (!Constants.BPMServiceMap.containsKey(wEventID)) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, "该流程暂不支持");
                return wResult;
            }
            BPMTaskService wBPMTaskService = Constants.BPMServiceMap.get(wEventID);
            String wMsg = "";

            List<BPMActivitiTask> wBPMActivitiTask = new ArrayList<>();

            // APSDayPlanAudit 单据状态为0且创建人是自己的任务
            // 创建审批单(先查询默认状态单据)
            ServiceResult<? extends BPMTaskBase> wServiceResult = wBPMTaskService.BPM_QueryDefaultTask(wLoginUser,
                    wTaskID,
                    wEventID.getValue());
            if (StringUtils.isNotEmpty(wServiceResult.FaultCode)) {

                return GetResult(RetCode.SERVER_CODE_ERR, wServiceResult.getFaultCode());
            }

            if (wServiceResult.getResult() == null
                    || (wServiceResult.getResult()).ID <= 0) {
                wServiceResult = wBPMTaskService.BPM_CreateTask(wLoginUser, wEventID);

                if (StringUtils.isNotEmpty(wServiceResult.FaultCode)) {
                    return GetResult(RetCode.SERVER_CODE_ERR, wServiceResult.getFaultCode());
                }
            }

            BPMTaskBase wData = wServiceResult.getResult();

            if (wParam.containsKey("data")) {
                StringUtils.CombineData(wData, wParam.get("data"));
            }
            if (wData.ID > 0) {
                wData.CreateTime = Calendar.getInstance();
                if (wData.FlowID <= 0) {
                    wData.FlowID = mBPMService.BPM_CreateProcess(wLoginUser, wEventID, wData.getID(), wData)
                            .Info(Integer.class);
                }
                if (wData.FlowID <= 0) {
                    wMsg += "创建流程失败！";
                } else {
                    wServiceResult = wBPMTaskService.BPM_SubmitTask(wLoginUser, wServiceResult.getResult());
                    if (wServiceResult.ErrorCode != 0) {
                        wMsg += wServiceResult.getFaultCode();
                    }

                    wBPMActivitiTask = mBPMService.BPM_GetTaskListByInstance(wLoginUser, wData.FlowID)
                            .List(BPMActivitiTask.class);
                }
            }

            if (wData == null) {
                wMsg += "该流程暂不支持";
            }
            if (StringUtils.isEmpty(wMsg)) {
                assert wData != null;
                wResult = GetResult(RetCode.SERVER_CODE_SUC, "", wBPMActivitiTask, wData.FlowID);
                SetResult(wResult, "data", wData);
            } else {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, wMsg);
            }
        } catch (Exception ex) {
            logger.error("startProcessByProcessDefinitionKey_MES", ex);
            wResult = GetResult(RetCode.SERVER_CODE_ERR, ex.toString());
        }
        return wResult;
    }

    /**
     * 提交待办任务
     */
    @PostMapping("/CompleteMyPersonalTask")
    public Object CompleteMyPersonalTask(HttpServletRequest request, @RequestBody Map<String, Object> wParam) {
        Object wResult = new Object();
        try {
            BMSEmployee wLoginUser = GetSession(request);

            if (!wParam.containsKey("TaskID") || !wParam.containsKey("data")) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, RetCode.SERVER_RST_ERROR_OUT);
                return wResult;
            }

            int wTaskID = CloneTool.Clone(wParam.get("TaskID"), Integer.class);
            BPMTaskBase wBPMTaskBase = CloneTool.Clone(wParam.get("data"), BPMTaskBase.class);
            int wLocalScope = wParam.containsKey("localScope") ? StringUtils.parseInt(wParam.get("localScope")) : 0;
            if (wTaskID <= 0 || wBPMTaskBase == null || wBPMTaskBase.ID <= 0) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, RetCode.SERVER_RST_ERROR_OUT);
                return wResult;
            }

            // ①判断任务是否已完成(防止任务重复提交)
            BPMActivitiHisTask wHisTask = mBPMService.BPM_GetTask(wLoginUser, wTaskID).Info(BPMActivitiHisTask.class);
            if (wHisTask == null || StringUtils.isEmpty(wHisTask.ID)) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, "提示：该任务不存在!");
                return wResult;
            } else if (wHisTask.Status == BPMHistoryTaskStatus.NomalFinished.getValue()
                    || wHisTask.Status == BPMHistoryTaskStatus.Canceled.getValue()) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, "提示：该任务已完成或已取消!");
                return wResult;
            }

            int wModuleID = wBPMTaskBase.getFlowType();
            BPMEventModule wEventID = BPMEventModule.getEnumType(wModuleID);

            if (!Constants.BPMServiceMap.containsKey(wEventID)) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, "该流程暂不支持");
                return wResult;
            }
            BPMTaskService wBPMTaskService = Constants.BPMServiceMap.get(wEventID);

            ServiceResult wServiceResult = null;
            BPMActivitiProcessInstance wBPMActivitiProcessInstance = null;

            ServiceResult<Boolean> wServiceResultBool = new ServiceResult<>(false);

            // ①提交任务单
            BPMTaskBase wTask = (BPMTaskBase) CloneTool.Clone(wParam.get("data"), wBPMTaskService.GetTClass());

            wServiceResultBool = this.mBPMService.BPM_MsgUpdate(wLoginUser, wTaskID, wLocalScope, wTask,
                    wParam.get("data"));
            if (wServiceResultBool.getResult() || !StringUtils.isEmpty(wServiceResultBool.getFaultCode())) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, "提交失败:" + wServiceResultBool.getFaultCode());
                return wResult;
            }
            wServiceResult = wBPMTaskService.BPM_SubmitTask(wLoginUser, wTask);

            wBPMActivitiProcessInstance = mBPMService.BPM_GetInstanceByID(wLoginUser, wTask.FlowID)
                    .Info(BPMActivitiProcessInstance.class);

            /*
             * 判断流程关闭
             */
            if (wBPMActivitiProcessInstance.DurationInMillis != null
                    && wBPMActivitiProcessInstance.DurationInMillis > 0
                    && StringUtils.isEmpty(wBPMActivitiProcessInstance.DeleteReason)
                    && (wTask.Status != BPMTaskStatus.Confirm.getValue() && wTask.Status != BPMTaskStatus.Rejected.getValue()
                    && wTask.Status != BPMTaskStatus.Canceled.getValue())) {
                // ①若流程关闭且状态非正常关闭与异常关闭则改为正常关闭
                wTask.Status = BPMTaskStatus.Confirm.getValue();
                wServiceResult = wBPMTaskService.BPM_SubmitTask(wLoginUser, wTask);
            }


            if (wServiceResult == null) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, "流程未配置!");
                return wResult;
            }
            List<BPMActivitiTask> wBPMActivitiTask = new ArrayList<>();
            if (wServiceResult.Result != null && ((BPMTaskBase) wServiceResult.Result).FlowID > 0) {
                wBPMActivitiTask = mBPMService
                        .BPM_GetTaskListByInstance(wLoginUser, ((BPMTaskBase) wServiceResult.Result).FlowID)
                        .List(BPMActivitiTask.class);
                if (wBPMActivitiTask != null) {
                    wBPMActivitiTask.removeIf(
                            p -> !StringUtils.parseIntList(p.Assignee.split(",")).contains(wLoginUser.getID()));
                }
            }
            if (StringUtils.isEmpty(wServiceResult.getFaultCode())) {
                wResult = GetResult(RetCode.SERVER_CODE_SUC, "", wBPMActivitiTask, wServiceResult.Result);
            } else {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, wServiceResult.getFaultCode());
            }
        } catch (Exception ex) {
            logger.error("CompleteMyPersonalTask", ex);
            wResult = GetResult(RetCode.SERVER_CODE_ERR, ex.toString());
        }
        return wResult;
    }

    /**
     * 撤销待办任务
     */
    @GetMapping("/deleteProcessInstance")
    public Object DeleteInstance(HttpServletRequest request) {
        Object wResult = new Object();
        try {
            BMSEmployee wLoginUser = GetSession(request);

            int wFlowID = StringUtils.parseInt(request.getParameter("processInstanceId"));
            int wID = StringUtils.parseInt(request.getParameter("ID"));
            int wFlowType = StringUtils.parseInt(request.getParameter("FlowType"));
            String wReason = StringUtils.parseString(request.getParameter("deleteReason"));

            if (StringUtils.isEmpty(wReason))
                wReason = "撤销";

            if (wFlowID <= 0) {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, RetCode.SERVER_RST_ERROR_OUT);
                return wResult;
            }

            APIResult wAPIResult = mBPMService.BPM_DeleteInstanceByID(wLoginUser, wFlowID, wReason);
            if (wAPIResult.getResultCode() != RetCode.SERVER_CODE_SUC)
                return wAPIResult;

            if (wFlowType > 0 && wID > 0) {
                BPMEventModule wEventID = BPMEventModule.getEnumType(wFlowType);
                if (!Constants.BPMServiceMap.containsKey(wEventID)) {
                    wResult = GetResult(RetCode.SERVER_CODE_ERR, "该流程暂不支持");
                    return wResult;
                }
                BPMTaskService wBPMTaskService = Constants.BPMServiceMap.get(wEventID);

                // ①提交任务单
                ServiceResult<? extends BPMTaskBase> wTaskResult = wBPMTaskService.BPM_GetTask(
                        wLoginUser,
                        wID);
                if (wTaskResult.Result != null && wTaskResult.Result.ID > 0) {
                    wTaskResult.Result.Status = BPMTaskStatus.Canceled.getValue();
                    wTaskResult.Result.StatusText = "已撤销";
                    if (wReason.contains("作废"))
                        wTaskResult.Result.StatusText = "已作废";
                    wTaskResult.Result.FollowerID = new ArrayList<>();

                    wBPMTaskService.BPM_SubmitTask(wLoginUser, wTaskResult.Result);
                } else {
                    wResult = GetResult(RetCode.SERVER_CODE_ERR, RetCode.SERVER_RST_ERROR_OUT);
                    return wResult;
                }
            }
            wResult = GetResult(RetCode.SERVER_CODE_SUC, "撤销成功！");
        } catch (Exception ex) {
            logger.error(ex.toString());
            wResult = GetResult(RetCode.SERVER_CODE_ERR, ex.toString());
        }
        return wResult;
    }

    /**
     * 生成待办消息
     */
    @GetMapping("/CreateToDoMessage")
    public Object CreateToDoMessage(HttpServletRequest request) {
        Object wResult = new Object();
        try {
            BMSEmployee wLoginUser = GetSession(request);

            int wFlowID = StringUtils.parseInt(request.getParameter("FlowID"));
            int wTaskID = StringUtils.parseInt(request.getParameter("TaskID"));
            int wModuleID = StringUtils.parseInt(request.getParameter("ModuleID"));
            String wCode = StringUtils.parseString(request.getParameter("Code"));

            if (wFlowID <= 0) {
                return GetResult(RetCode.SERVER_CODE_ERR, RetCode.SERVER_RST_ERROR_OUT);
            }

            ServiceResult<Integer> wServiceResult = mBPMService.BPM_CreateToDoMessage(wLoginUser, wFlowID, wTaskID,
                    wModuleID, wCode);

            if (StringUtils.isEmpty(wServiceResult.FaultCode)) {
                wResult = GetResult(RetCode.SERVER_CODE_SUC, "", null, wServiceResult.Result);
            } else {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, wServiceResult.FaultCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
            wResult = GetResult(RetCode.SERVER_CODE_ERR, ex.toString());
        }
        return wResult;
    }

    /**
     * 驳回指定节点
     */
    @PostMapping("/RejectTo")
    public Object RejectTo(HttpServletRequest request, @RequestBody Map<String, Object> wParam) {
        Map<String, Object> wResult;
        try {
            BMSEmployee wLoginUser = GetSession(request);

            // 获取参数
            String wTaskID = StringUtils.parseString(wParam.get("TaskID"));
            String targetActivityId = StringUtils.parseString(wParam.get("targetActivityId"));
            Object wData = wParam.get("data");
            String targetActivityName = StringUtils.parseString(wParam.get("targetActivityName"));
            int wFlowType = StringUtils.parseInt(wParam.get("FlowType"));

            ServiceResult<Object> wServiceResult = mBPMService.BPM_RejectTo(wLoginUser, wTaskID, targetActivityId,
                    wData, targetActivityName, wFlowType);

            if (StringUtils.isEmpty(wServiceResult.FaultCode)) {
                wResult = GetResult(RetCode.SERVER_CODE_SUC, "", new ArrayList<Integer>(), wData);
            } else {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, wServiceResult.FaultCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
            wResult = GetResult(RetCode.SERVER_CODE_ERR, ex.toString());
        }
        return wResult;
    }

    /**
     * 同步用户
     */
    @GetMapping("/SynchronizUser")
    public Object SynchronizUser(HttpServletRequest request) {
        Object wResult = new Object();
        try {
            BMSEmployee wLoginUser = GetSession(request);

            ServiceResult<Integer> wServiceResult = mBPMService.BPM_SynchronizUser(wLoginUser);

            if (StringUtils.isEmpty(wServiceResult.FaultCode)) {
                wResult = GetResult(RetCode.SERVER_CODE_SUC, "", null, wServiceResult.Result);
            } else {
                wResult = GetResult(RetCode.SERVER_CODE_ERR, wServiceResult.FaultCode);
            }
        } catch (Exception ex) {
            logger.error(ex.toString());
            wResult = GetResult(RetCode.SERVER_CODE_ERR, ex.toString());
        }
        return wResult;
    }
}
